import sys
import socket
#from twisted.internet import reactor
from txosc import osc#, dispatch, async

if __name__ == '__main__':
    import sys, os
    p = os.path.split(os.getcwd())[0]
    sys.path.append(os.path.split(p)[0])

from ..BaseIO import BaseIO

ANY = '0.0.0.0'

class BaseOSCSender(BaseIO):
    def __init__(self, **kwargs):
        super(BaseOSCSender, self).__init__(**kwargs)
        self.root_address = kwargs.get('root_address')
        self.hostaddr = kwargs.get('hostaddr', 'localhost')
        self.hostport = int(kwargs.get('hostport', 18889))
        self.client = None
        #self.connected = False
        self.debug = 'debug-osc' in sys.argv
        
    def do_connect(self, **kwargs):
        self.do_disconnect()
        for key, val in kwargs.iteritems():
            if key in ['hostaddr', 'hostport']:
                setattr(self, key, val)
        self.build_socket()
        self.connected = True
        #self.emit('state_changed', state=True)
        
    def do_disconnect(self, **kwargs):
        if self.client is not None:
            self.client.close()
            self.client = None
            self.connected = False
            #self.emit('state_changed', state=False)
            
    def _send(self, element, address):
        if self.connected:
            self.client.sendto(element.toBinary(), 0, address)
            if self.debug:
                print '_send: ', element.address, element.getValues(), address
            
class MulticastOSCSender(BaseOSCSender):
    def __init__(self, **kwargs):
        super(MulticastOSCSender, self).__init__(**kwargs)
        self.mcastaddr = kwargs.get('mcastaddr', '224.168.2.9')
        self.mcastport = kwargs.get('mcastport', 18888)
        
    def do_connect(self, **kwargs):
        for key, val in kwargs.iteritems():
            if key in ['mcastaddr', 'mcastport']:
                setattr(self, key, val)
        super(MulticastOSCSender, self).do_connect(**kwargs)
        
    def build_socket(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 
                                    socket.IPPROTO_UDP)
        self.client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.client.bind((ANY, self.hostport))
        self.client.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
    
    def _send(self, element):
        super(MulticastOSCSender, self)._send(element, (self.mcastaddr, self.mcastport))
        
class UnicastOSCSender(BaseOSCSender):
    def build_socket(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 
                                    socket.IPPROTO_UDP)
        #self.client.bind(('', 0))
        
    def _send(self, element, address):
        if type(address) == str:
            addr = (address, self.hostport)
        else:
            addr = address
        super(UnicastOSCSender, self)._send(element, addr)

class oldMulticastOSCSender(BaseIO):
    def __init__(self, **kwargs):
        super(oldMulticastOSCSender, self).__init__(**kwargs)
        self.root_address = kwargs.get('root_address')
        self.hostaddr = kwargs.get('host', '224.0.0.1')
        self.hostport = int(kwargs.get('port', 18888))
        self.client = async.DatagramClientProtocol()
        self.connected = False
    def do_connect(self, **kwargs):
        
        self._client_port = reactor.listenUDP(0, self.client)
        self.connected = True
        self.emit('state_changed', state=True)
        print 'connect'
    def do_disconnect(self, **kwargs):
        self._client_port.disconnect()
        self.connected = False
        self.emit('state_changed', state=False)
        

    def _send(self, element):
        if self.connected:
            self.client.send(element, (self.hostaddr, self.hostport))
            print '_send: ', element.address, element.getValues()
            #print("Sent %s to %s:%d" % (element, self.hostaddr, self.hostport))

if __name__ == "__main__":
    app = MulticastOSCSender()
    app.do_connect()
    reactor.callLater(0, app.send_spam)
    reactor.run()
